@inherits MiniRazor.TemplateBase<CodeEntity>
@namespace OSharp.CodeGeneration.Templates
@using System;
@using System.Collections.Generic
@using System.Linq
@using OSharp.CodeGeneration.Services.Entities
@using OSharp.CodeGeneration.Utils
@using OSharp.Collections;
@using OSharp.Exceptions;
@using OSharp.Extensions;
@{
  CodeEntity entity = Model;
  string keyType = TypeHelper.ToSingleTypeName(entity.PrimaryKeyTypeFullName);
  string[] spaces = entity.Properties.Where(m => m.RelateEntity != null).Select(m => TypeHelper.GetNamespace(m.RelateEntity))
    .Distinct().Where(m => m != entity.Module.Namespace + ".Entities").ToArray();
}//------------------------------------------------------------------------------
// <auto-generated>
//    此代码由代码生成器生成。
//    手动更改此文件可能导致应用程序出现意外的行为。
//    如果重新生成代码，对此文件的任何修改都会丢失。
//    如果需要扩展此类：可遵守如下规则进行扩展：
//      1.横向扩展：如需添加额外的映射，可新建文件“@(entity.Name)Configuration.cs”的分部类“public partial class @(entity.Name)Configuration”实现分部方法 EntityConfigurationAppend 进行扩展
// </auto-generated>
//
// <copyright file="@(entity.Name)Configuration.generated.cs" company="@entity.Module.Project.Company">
//     @entity.Module.Project.Copyright
// </copyright>
// <site>@entity.Module.Project.SiteUrl</site>
// <last-editor>@entity.Module.Project.Creator</last-editor>
// -----------------------------------------------------------------------

using System;
using System.Collections.Generic;

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

using OSharp.Entity;

using @(entity.Module.Namespace).Entities;
@foreach (var space in spaces)
{
<text>using @(space);</text>
}


namespace @(entity.Module.Project.NamespacePrefix).EntityConfiguration.@entity.Module.Name
{
    /// &lt;summary&gt;
    /// 实体配置类：@(entity.Display)信息
    /// &lt;/summary&gt;
    public partial class @(entity.Name)Configuration : EntityTypeConfigurationBase&lt;@(entity.Name), @(keyType)&gt;
    {
        /// &lt;summary&gt;
        /// 重写以实现实体类型各个属性的数据库配置
        /// &lt;/summary&gt;
        /// &lt;param name="builder"&gt;实体类型创建器&lt;/param&gt;
        public override void Configure(EntityTypeBuilder&lt;@entity.Name&gt; builder)
        {
@foreach (var foreign in entity.Foreigns)
{
<text>            @GetForeign(foreign, entity)
</text>
}

            EntityConfigurationAppend(builder);
        }

        /// <summary>
        /// 额外的数据映射
        /// </summary>
        partial void EntityConfigurationAppend(EntityTypeBuilder&lt;@entity.Name&gt; builder);
    }
}

@functions
{


    static string GetForeign(CodeForeign foreign, CodeEntity entity)
    {
      List<string> list = new List<string>();

      list.Add("builder");
      list.Add(Relation(foreign, entity));
      list.Add(";");

      return list.ExpandAndToString("");
    }
    
    private static string Relation(CodeForeign foreign, CodeEntity entity)
    { 
      string line = string.Empty;
      switch (foreign.ForeignRelation)
      {
        case ForeignRelation.OneToMany:
          line += ".HasMany";
          break;
        case ForeignRelation.ManyToOne:
          line += ".HasOne";
          break;
        case ForeignRelation.OneToOne:
          line += ".HasOne";
          break;
        case ForeignRelation.OwnsOne:
          line += ".OwnsOne";
          break;
        case ForeignRelation.OwnsMany:
          line += ".OwnsMany";
          break;
        default:
          throw new ArgumentOutOfRangeException();
      }

      if (!string.IsNullOrEmpty(foreign.OtherEntity))
      {
        line += $"<{TypeHelper.ToSingleTypeName(foreign.OtherEntity)}>";
      }
      line += "(";
      if (!string.IsNullOrEmpty(foreign.SelfNavigation))
      {
        line += $"m => m.{foreign.SelfNavigation}";
      }
      line += ")";
      switch (foreign.ForeignRelation)
      {
        case ForeignRelation.OneToMany:
          line += ".WithOne(";
          break;
        case ForeignRelation.ManyToOne:
          line += ".WithMany(";
          break;
        case ForeignRelation.OneToOne:
          line += ".WithOne(";
          break;
        case ForeignRelation.OwnsOne:
          break;
        case ForeignRelation.OwnsMany:
          break;
        default:
          throw new ArgumentOutOfRangeException();
      }
      if (!new []{ForeignRelation.OwnsOne, ForeignRelation.OwnsMany}.Contains(foreign.ForeignRelation))
      {
        if (!string.IsNullOrEmpty(foreign.OtherNavigation))
        {
          line += $"n => n.{foreign.OtherNavigation})";
        }
        else
        {
          line += ")";
        }
        if (!string.IsNullOrEmpty(foreign.SelfForeignKey))
        {
          line += ".HasForeignKey";
          if (foreign.ForeignRelation == ForeignRelation.OneToOne)
          {
            line += $"<{TypeHelper.ToSingleTypeName(entity.Name)}>";
          }
          line += $"(m => m.{foreign.SelfForeignKey})";
        }
        if (foreign.IsRequired)
        {
          line += ".IsRequired()";
        }
        if (foreign.DeleteBehavior != null)
        {
          line += $".OnDelete(DeleteBehavior.{foreign.DeleteBehavior.Value})";
        }
      }
      return line;
    }
}
